package cn.chiship.sdk.core.util;

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;

/**
 * 对文件或文件夹进行压缩和解压
 *
 * @author lijian
 */
public class ZipUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(ZipUtil.class);

	public static boolean zip(String srcFileName, String descFileName, String extName) {
		return zip(srcFileName, descFileName, null, extName);
	}

	public static boolean zip(String srcFileName, String descFileName, String password, String extName) {
		LOGGER.info("开始压缩");
		if (StringUtil.isNullOrEmpty(srcFileName) || StringUtil.isNullOrEmpty(descFileName)) {
			return false;
		}
		try {
			ZipParameters parameters = new ZipParameters();
			parameters.setCompressionMethod(CompressionMethod.DEFLATE);
			parameters.setCompressionLevel(CompressionLevel.NORMAL);
			if (!StringUtil.isNullOrEmpty(password)) {
				parameters.setEncryptFiles(true);
				parameters.setEncryptionMethod(EncryptionMethod.AES);
				parameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
			}
			ArrayList<File> filesToAdd = new ArrayList<>();
			File file = new File(srcFileName);
			File[] files;
			if (file.isDirectory()) {
				files = file.listFiles();
				for (int i = 0; i < files.length; i++) {
					if (files[i].isFile()) {
						String fileExt = files[i].getName().substring(files[i].getName().lastIndexOf(".") + 1);
						if (extName.indexOf(fileExt) > -1) {
							filesToAdd.add(new File(srcFileName + files[i].getName()));
						}
					}
				}
			}
			else {
				String fileExt = file.getName().substring(file.getName().lastIndexOf(".") + 1);
				if (extName.indexOf(fileExt) > -1) {
					filesToAdd.add(file);
				}

			}
			ZipFile zipFile;
			if (!StringUtil.isNullOrEmpty(password)) {
				zipFile = new ZipFile(descFileName + ".zip", password.toCharArray());
			}
			else {
				zipFile = new ZipFile(descFileName + ".zip");
			}
			zipFile.addFiles(filesToAdd, parameters);
			return true;
		}
		catch (Exception e) {
			LOGGER.error("文件压缩出错", e);
			return false;
		}
	}

	public static void zip(String srcFileName, OutputStream os, String extName) {
		zip(srcFileName, os, null, extName);
	}

	public static void zip(String srcFileName, OutputStream os, String password, String extName) {
		ZipOutputStream outputStream = null;
		InputStream inputStream = null;
		try {
			if (!StringUtil.isNullOrEmpty(password)) {
				outputStream = new ZipOutputStream(os, password.toCharArray());
			}
			else {
				outputStream = new ZipOutputStream(os);
			}
			ZipParameters parameters = new ZipParameters();
			parameters.setCompressionMethod(CompressionMethod.DEFLATE);
			parameters.setCompressionLevel(CompressionLevel.NORMAL);
			if (!StringUtil.isNullOrEmpty(password)) {
				parameters.setEncryptFiles(true);
				parameters.setEncryptionMethod(EncryptionMethod.AES);
				parameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
			}
			ArrayList<File> filesToAdd = new ArrayList<>();
			File file = new File(srcFileName);
			File[] files;
			if (file.isDirectory()) {
				files = file.listFiles();
				for (int i = 0; i < files.length; i++) {
					if (files[i].isFile()) {
						String fileExt = files[i].getName().substring(files[i].getName().lastIndexOf(".") + 1);
						if (extName.indexOf(fileExt) > -1) {
							filesToAdd.add(new File(srcFileName + files[i].getName()));
							LOGGER.info("文件名称：" + files[i].getName());
						}
					}
				}
			}
			else {
				String fileExt = file.getName().substring(file.getName().lastIndexOf(".") + 1);
				if (extName.indexOf(fileExt) > -1) {
					filesToAdd.add(file);
					LOGGER.info("文件名称：" + file.getName());
				}

			}
			for (File f : filesToAdd) {
				parameters.setFileNameInZip(f.getName());
				outputStream.putNextEntry(parameters);
				inputStream = new FileInputStream(f);
				byte[] readBuff = new byte[4096];
				int readLen = -1;
				while ((readLen = inputStream.read(readBuff)) != -1) {
					outputStream.write(readBuff, 0, readLen);
				}
				outputStream.closeEntry();
				inputStream.close();
			}
		}
		catch (Exception e) {
		}
		finally {
			if (outputStream != null) {
				try {
					outputStream.close();
				}
				catch (IOException e) {
					LOGGER.error("发生异常", e);
				}
			}

			if (inputStream != null) {
				try {
					inputStream.close();
				}
				catch (IOException e) {
					LOGGER.error("发生异常", e);
				}
			}
		}
	}

	public static boolean unZip(String srcFileName, String descFile) {
		return unZip(srcFileName, descFile, null);
	}

	public static boolean unZip(String srcFileName, String descFile, String password) {
		try {
			ZipFile zipFile = new ZipFile(srcFileName + ".zip");
			if (zipFile.isEncrypted()) {
				zipFile.setPassword(password.toCharArray());
			}
			zipFile.extractAll(descFile);
			return true;
		}
		catch (ZipException e) {
			LOGGER.error("发生异常", e);
			return false;
		}

	}

	public static void main(String[] args) throws Exception {
		// ZipUtil.unZip("D://济阳十中", "d://1/1");
		// zip("D:\\济阳十中2021级5班(张新奥) - 副本.pdf", "D:\\济阳十中1", "123456", "pdf,dll");
		OutputStream outputStream = new FileOutputStream("D://济阳十中1111112111.zip");
		zip("D:\\", outputStream, "23456", "pdf");
	}

}